# 5.黄金交易模拟赛


import numpy as np
import datetime
import matplotlib.pyplot as plt
from matplotlib.dates import DateFormatter
from matplotlib import rcParams

# 设置Matplotlib字体和中文显示配置
config = {
    "font.family": 'serif',  # 使用衬线字体
    "font.size": 15,  # 设置字体大小
    "mathtext.fontset": 'stix',  # 设置数学公式字体
    "font.serif": ['SimSun'],  # 设置中文字体为宋体
}
rcParams.update(config)

# 导入金价数据
import gold

prices = gold.prices
price_dict = {datetime.datetime.strptime(date, "%Y-%m-%d"): price for date, price in prices}


# 定义计算投资总额和累计收益的函数
def CalcGain(start_date, end_date):
    start_date = datetime.datetime.strptime(start_date, "%Y-%m-%d")
    end_date = datetime.datetime.strptime(end_date, "%Y-%m-%d")

    # 生成日期范围数组，包含从开始买入日到卖出日的所有日期
    date_range = np.array([start_date + datetime.timedelta(days=i) for i in range((end_date - start_date).days + 1)])
    valid_dates = np.array([date for date in date_range if date in price_dict])
    prices_array = np.array([price_dict[date] for date in valid_dates])

    amounts = 1000 / prices_array
    total_investment = len(valid_dates) * 1000  # 投资总额
    gold_amount = np.sum(amounts)  # 购买的黄金数量
    total_money = gold_amount * price_dict[end_date] - total_investment  # 累计收益

    return total_investment, total_money, valid_dates, prices_array


max_return = 0  # 最大的累计收益值
best_start = None  # 最佳的买入日期
best_end = None  # 最佳的卖出日期

# 寻找最佳的买入日期和卖出日期
for start_date in price_dict.keys():  # 外层循环，遍历金价数据中的所有日期作为买入日期（start_date）进行尝试。
    for end_date in price_dict.keys(): # 内层循环，对于每一个买入日期，再次遍历金价数据中的所有日期作为卖出日期（end_date）进行尝试。
        if end_date > start_date: # 确保卖出日期晚于买入日期，避免出现买入日期晚于卖出日期的情况，保证交易逻辑的正确性
            _, total_money, _, _ = CalcGain(start_date.strftime("%Y-%m-%d"), end_date.strftime("%Y-%m-%d"))
            if total_money > max_return:
                max_return = total_money
                best_start = start_date
                best_end = end_date

print('最佳买入日期:', best_start.strftime("%Y-%m-%d"))
print('最佳卖出日期:', best_end.strftime("%Y-%m-%d"))
print('最大累计收益:', max_return)

# 绘制可视化结果
total_investment, total_money, valid_dates, prices_array = CalcGain(best_start.strftime("%Y-%m-%d"),
                                                                    best_end.strftime("%Y-%m-%d"))

day_money = np.cumsum(1000 / prices_array * prices_array[-1] - 1000)

plt.figure(figsize=(24, 10))
plt.plot(valid_dates, day_money, marker='o', linestyle='-', label='每日累计收益')
plt.xlabel('日期')
plt.ylabel('累计收益')
plt.title('最佳黄金交易时间段每日累计收益')
plt.xticks(rotation=50)
plt.gca().xaxis.set_major_formatter(DateFormatter('%Y-%m-%d'))
plt.grid(True)

# 在每隔30天的日期点处显示累计收益的数值
for i in range(0, len(valid_dates), 30):
    plt.text(valid_dates[i], day_money[i], '{:.2f}'.format(day_money[i]), ha='center', va='bottom')

plt.legend()
plt.show()
